package com.xh3140.android.widget.dialog;

import android.content.Context;

import androidx.annotation.ColorInt;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.annotation.Size;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;

import com.xh3140.android.widget.dialog.callback.ConfigParamsCallback;
import com.xh3140.android.widget.dialog.callback.ConfigParamsListCallback;
import com.xh3140.android.widget.dialog.callback.ConfigViewCallback;
import com.xh3140.android.widget.dialog.params.BaseParams;
import com.xh3140.android.widget.dialog.params.DialogParams;
import com.xh3140.android.widget.dialog.params.ItemParams;
import com.xh3140.android.widget.dialog.params.ListParams;
import com.xh3140.android.widget.dialog.view.FooterView;
import com.xh3140.android.widget.dialog.view.HeaderView;
import com.xh3140.android.widget.dialog.view.ItemView;
import com.xh3140.android.widget.dialog.view.ListView;
import com.xh3140.android.widget.dialog.view.RootView;

import java.util.Arrays;
import java.util.List;

/**
 * 列表对话框
 */
@SuppressWarnings("unused")
public final class ListDialog extends BaseDialog<ListView> {
    /**
     * 列表对话框属性
     */
    private final Params mParams;

    /**
     * 列表对话框属性数据类
     */
    private static final class Params {
        public final DialogParams dialog;
        public final BaseParams<ListDialog> base;
        public final ListParams list;

        private Params(@NonNull DialogParams dialog, @NonNull BaseParams<ListDialog> base, @NonNull ListParams list) {
            this.dialog = dialog;
            this.base = base;
            this.list = list;
        }
    }

    private ListDialog(@NonNull Params params) {
        super(params.dialog);
        mParams = params;
    }

    /**
     * 获取单选的选取位置索引
     * 注意：没有选中任何项目时返回负数(-1)
     */
    public int getCheckedIndex() {
        return requireRootView().requireBodyView().getCheckedIndex();
    }

    /**
     * 获取多选的选取位置索引列表
     * 注意：没有选中任何项目时返回空列表
     */
    public List<Integer> getCheckedIndexList() {
        return requireRootView().requireBodyView().getCheckedIndexList();
    }

    @NonNull
    @Override
    protected RootView<ListView> initRootView(@NonNull Context context) {
        final ListDialog dialog = this;
        return new RootView<ListView>(context) {
            @Override
            protected HeaderView initHeaderView(@NonNull Context context) {
                return new HeaderView(context, mParams.base.header);
            }

            @Override
            protected ListView initBodyView(@NonNull Context context) {
                return new ListView(context, mParams.list);
            }

            @Override
            protected FooterView initFooterView(@NonNull Context context) {
                return new FooterView(context, dialog, mParams.base.footer);
            }
        };
    }

    /**
     * 列表对话框构建器
     * 设置输入对话框属性
     */
    public static final class Builder extends BaseDialog.Builder<ListDialog, Builder> {
        /**
         * 对话框列表主体视图配置属性
         */
        private final ListParams mListParams;

        public Builder(@NonNull Context context, @IntRange(from = 0) int buttonCount, @IntRange(from = 0) int itemCount) {
            super(context, buttonCount);
            mListParams = new ListParams(context, itemCount);
        }

        public Builder(@NonNull FragmentActivity activity, @IntRange(from = 0) int buttonCount, @IntRange(from = 0) int itemCount) {
            super(activity, buttonCount);
            mListParams = new ListParams(mDialogParams.context, itemCount);
        }

        public Builder(@NonNull Fragment fragment, @IntRange(from = 0) int buttonCount, @IntRange(from = 0) int itemCount) {
            super(fragment, buttonCount);
            mListParams = new ListParams(mDialogParams.context, itemCount);
        }

        /**
         * 构建对话框
         * 这个方法应该在所有配置结束后调用
         */
        @Override
        public ListDialog build() {
            return new ListDialog(new Params(mDialogParams, mBaseParams, mListParams));
        }

        /**
         * 配置列表主体视图属性
         *
         * @param callback 配置回调
         */
        public Builder configListParams(@NonNull ConfigParamsCallback<ListParams> callback) {
            callback.callback(mListParams);
            return this;
        }

        /**
         * 配置列表主体视图项目属性
         *
         * @param position 项目位置索引
         * @param callback 配置回调
         */
        public Builder configListItemParams(int position, @NonNull ConfigParamsCallback<ItemParams> callback) {
            callback.callback(mListParams.items.get(position));
            return this;
        }

        /**
         * 配置列表主体视图所有项目属性
         *
         * @param callback 配置回调
         */
        public Builder configListItemsParams(@NonNull ConfigParamsListCallback<ItemParams> callback) {
            callback.callback(mListParams.items);
            return this;
        }

        /**
         * 设置列表主体视图项目按钮是否在右边
         *
         * @param right 是否在右边
         */
        public Builder setListButtonOnRight(boolean right) {
            mListParams.isRight = right;
            return this;
        }

        /**
         * 设置列表主体视图是否是单选列表
         *
         * @param isSingle 是否是单选列表
         */
        public Builder setListIsSingle(boolean isSingle) {
            mListParams.isSingle = isSingle;
            return this;
        }

        /**
         * 设置列表主体视图是否有分割线
         *
         * @param hasDivider 标志
         */
        public Builder setListHasDivider(boolean hasDivider) {
            mListParams.hasDivider = hasDivider;
            return this;
        }

        /**
         * 设置列表主体视图分割线颜色
         *
         * @param color 颜色 argb
         */
        public Builder setListDividerColor(@ColorInt int color) {
            mListParams.hasDivider = true;
            mListParams.dividerColor = color;
            return this;
        }

        /**
         * 设置列表主体视图分割线厚度 px
         *
         * @param thickness 厚度 px
         */
        public Builder setListDividerThickness(int thickness) {
            mListParams.hasDivider = true;
            mListParams.dividerThickness = thickness;
            return this;
        }

        /**
         * 设置列表主体视图单选默认的选取位置索引
         *
         * @param index 位置索引
         */
        public Builder setCheckedIndex(int index) {
            mListParams.isSingle = true;
            mListParams.checkedIndex = index;
            mListParams.items.get(index).isChecked = true;
            return this;
        }

        /**
         * 设置列表主体视图多选默认的选取位置索引组
         *
         * @param indexList 位置索引组
         */
        public Builder setCheckedIndexList(List<Integer> indexList) {
            mListParams.isSingle = false;
            mListParams.checkedIndexList = indexList;
            for (Integer index : indexList) {
                mListParams.items.get(index).isChecked = true;
            }
            return this;
        }

        /**
         * 设置列表主体视图多选默认的选取位置索引组
         *
         * @param indexArray 位置索引组
         */
        public Builder setCheckedIndexList(Integer... indexArray) {
            mListParams.isSingle = false;
            mListParams.checkedIndexList = Arrays.asList(indexArray);
            for (Integer index : indexArray) {
                mListParams.items.get(index).isChecked = true;
            }
            return this;
        }

        /**
         * 设置列表主体视图配置回调
         * 拥有绝对控制权的回调，它在其他属性配置结束后回调
         * 一般情况不要使用它，除非提供的现有配置属性不满足需求
         *
         * @param callback 配置回调
         */
        public Builder setListViewCallback(@Nullable ConfigViewCallback<ListView> callback) {
            mListParams.callback = callback;
            return this;
        }

        /**
         * 设置列表主体视图项目文本列表
         *
         * @param texts 项目文本列表
         */
        public Builder setListItemsText(List<CharSequence> texts) {
            for (int i = 0; i < texts.size(); ++i) {
                mListParams.items.get(i).text = texts.get(i);
            }
            return this;
        }

        /**
         * 设置列表主体视图项目文本列表
         *
         * @param texts 项目文本列表
         */
        public Builder setListItemsText(CharSequence... texts) {
            for (int i = 0; i < texts.length; ++i) {
                mListParams.items.get(i).text = texts[i];
            }
            return this;
        }

        /**
         * 设置列表主体视图项目文本列表
         *
         * @param index 单选默认的选取位置索引
         * @param texts 项目文本列表
         */
        public Builder setListItemsText(int index, List<CharSequence> texts) {
            mListParams.isSingle = true;
            mListParams.checkedIndex = index;
            mListParams.items.get(index).isChecked = true;
            for (int i = 0; i < texts.size(); ++i) {
                mListParams.items.get(i).text = texts.get(i);
            }
            return this;
        }

        /**
         * 设置列表主体视图项目文本列表
         *
         * @param index 单选默认的选取位置索引
         * @param texts 项目文本列表
         */
        public Builder setListItemsText(int index, CharSequence... texts) {
            mListParams.isSingle = true;
            mListParams.checkedIndex = index;
            mListParams.items.get(index).isChecked = true;
            for (int i = 0; i < texts.length; ++i) {
                mListParams.items.get(i).text = texts[i];
            }
            return this;
        }

        /**
         * 设置列表主体视图项目文本列表
         *
         * @param indexList 多选默认的选取位置索引组
         * @param texts     项目文本列表
         */
        public Builder setListItemsText(List<Integer> indexList, List<CharSequence> texts) {
            mListParams.isSingle = false;
            mListParams.checkedIndexList = indexList;
            for (Integer index : indexList) {
                mListParams.items.get(index).isChecked = true;
            }
            for (int i = 0; i < texts.size(); ++i) {
                mListParams.items.get(i).text = texts.get(i);
            }
            return this;
        }

        /**
         * 设置列表主体视图项目文本列表
         *
         * @param indexList 多选默认的选取位置索引组
         * @param texts     项目文本列表
         */
        public Builder setListItemsText(List<Integer> indexList, CharSequence... texts) {
            mListParams.isSingle = false;
            mListParams.checkedIndexList = indexList;
            for (Integer index : indexList) {
                mListParams.items.get(index).isChecked = true;
            }
            for (int i = 0; i < texts.length; ++i) {
                mListParams.items.get(i).text = texts[i];
            }
            return this;
        }

        /**
         * 设置列表主体视图项目是否被选中
         *
         * @param position 项目位置索引
         * @param checked  是否被选中
         */
        public Builder setListItemChecked(int position, boolean checked) {
            mListParams.items.get(position).isChecked = checked;
            return this;
        }

        /**
         * 设置列表主体视图项目文本字体大小 sp
         *
         * @param position 项目位置索引
         * @param textSize 字体大小
         */
        public Builder setListItemTextSize(int position, float textSize) {
            mListParams.items.get(position).textSize = textSize;
            return this;
        }

        /**
         * 设置列表主体视图项目文本字体颜色 argb
         *
         * @param position  项目位置索引
         * @param textColor 字体颜色
         */
        public Builder setListItemTextColor(int position, @ColorInt int textColor) {
            mListParams.items.get(position).textColor = textColor;
            return this;
        }

        /**
         * 设置列表主体视图项目文本字体样式
         *
         * @param position 项目位置索引
         * @param typeface 字体样式
         */
        public Builder setListItemTypeface(int position, int typeface) {
            mListParams.items.get(position).typeface = typeface;
            return this;
        }

        /**
         * 设置列表主体视图项目文本位置
         *
         * @param position 项目位置索引
         * @param gravity  位置
         */
        public Builder setListItemGravity(int position, int gravity) {
            mListParams.items.get(position).gravity = gravity;
            return this;
        }

        /**
         * 设置列表主体视图项目背景颜色 argb
         *
         * @param position        项目位置索引
         * @param backgroundColor 背景颜色
         */
        public Builder setListItemBackgroundColor(int position, @ColorInt int backgroundColor) {
            mListParams.items.get(position).backgroundColor = backgroundColor;
            return this;
        }

        /**
         * 设置列表主体视图项目内边距
         * <p>
         * 格式：[start, top, end, bottom] px
         *
         * @param position 项目位置索引
         * @param padding  边距
         */
        public Builder setListItemPadding(int position, @Nullable @Size(4) int[] padding) {
            mListParams.items.get(position).padding = padding;
            return this;
        }

        /**
         * 设置列表主体视图项目内边距
         *
         * @param position 项目位置索引
         * @param padding  边距 px
         */
        public Builder setListItemPadding(int position, @Px int padding) {
            mListParams.items.get(position).padding = new int[]{padding, padding, padding, padding};
            return this;
        }

        /**
         * 设置列表主体视图项目内边距
         *
         * @param position 项目位置索引
         * @param left     左边距 px
         * @param top      上边距 px
         * @param right    右边距 px
         * @param bottom   下边距 px
         */
        public Builder setListItemPadding(int position, @Px int left, @Px int top, @Px int right, @Px int bottom) {
            mListParams.items.get(position).padding = new int[]{left, top, right, bottom};
            return this;
        }

        /**
         * 设置列表主体视图项目外边距
         *
         * 格式：[start, top, end, bottom] px
         *
         * @param position 项目位置索引
         * @param margins  边距
         */
        public Builder setListItemMargins(int position, @Nullable @Size(4) int[] margins) {
            mListParams.items.get(position).margins = margins;
            return this;
        }

        /**
         * 设置列表主体视图项目外边距
         *
         * @param position 项目位置索引
         * @param margins  边距 px
         */
        public Builder setListItemMargins(int position, @Px int margins) {
            mListParams.items.get(position).margins = new int[]{margins, margins, margins, margins};
            return this;
        }

        /**
         * 设置列表主体视图项目外边距
         *
         * @param position 项目位置索引
         * @param left     左边距 px
         * @param top      上边距 px
         * @param right    右边距 px
         * @param bottom   下边距 px
         */
        public Builder setListItemMargins(int position, @Px int left, @Px int top, @Px int right, @Px int bottom) {
            mListParams.items.get(position).margins = new int[]{left, top, right, bottom};
            return this;
        }

        /**
         * 设置列表主体视图项目高度 px
         *
         * @param position 项目位置索引
         * @param height   高度
         */
        public Builder setListItemHeight(int position, @Px int height) {
            mListParams.items.get(position).height = height;
            return this;
        }

        /**
         * 设置列表主体视图项目配置回调
         * 拥有绝对控制权的回调，它在其他属性配置结束后回调
         * 一般情况不要使用它，除非提供的现有配置属性不满足需求
         *
         * @param position 项目位置索引
         * @param callback 配置回调
         */
        public Builder setListItemViewCallback(int position, @Nullable ConfigViewCallback<ItemView> callback) {
            mListParams.items.get(position).callback = callback;
            return this;
        }
    }
}
